#include "message.h"
#include "../hostdep/end_util.h"
#include "bit_util.h"

void set_message_id(unsigned char* message, uint32_t message_id) {
    ((uint32_t*)message)[0] = hbo2nbo32(message_id);
}

void set_device_id(unsigned char* message, uint16_t device_id) {
    ((uint16_t*)message)[2] = hbo2nbo16(device_id);
}

void set_message_info(unsigned char* message, message_type type,
  message_delivery delivery, message_scope scope, message_direction direction, 
  uint16_t msg_number) {
    uint16_t msg_info;
    
    if (msg_number > 4095) {
        /* TODO: service this case */
        msg_number = 0;
    }

    msg_info = ((uint16_t)type << 15) | ((uint16_t)delivery << 14) | 
        ((uint16_t)scope << 13) | ((uint16_t)direction << 12) | msg_number;
    ((uint16_t*)message)[3] = hbo2nbo16(msg_info);
}

uint32_t get_message_id(unsigned char* message) {
    return ((uint32_t*)message)[0];
}

uint16_t get_device_id(unsigned char* message) {
    return ((uint16_t*)message)[2];
}

message_type get_message_type(unsigned char* message) {
    uint16_t msg_info = ((uint16_t*) message)[3];
    if (!get_bit_value_16(msg_info, 15)) {
        return MSG_TYPE_CONTROL;
    } else {
        return MSG_TYPE_DATA;
    }
}

message_delivery get_message_delivery(unsigned char* message) {
    uint16_t msg_info = ((uint16_t*) message)[3];
    if (!get_bit_value_16(msg_info, 14)) {
        return MSG_DELIVERY_SYNC;
    } else {
        return MSG_DELIVERY_ASYNC;
    }
}

message_scope get_message_scope(unsigned char* message) {
    uint16_t msg_info = ((uint16_t*) message)[3];
    if (!get_bit_value_16(msg_info, 13)) {
        return MSG_SCOPE_GLOBAL;
    } else {
        return MSG_SCOPE_DEVICE_SPECIFIC;
    }
}

message_direction get_message_direction(unsigned char* message) {
    uint16_t msg_info = ((uint16_t*) message)[3];
    if (!get_bit_value_16(msg_info, 12)) {
        return MSG_DIRECTION_REQUEST;
    } else {
        return MSG_DIRECTION_RESPONSE;
    }
}

uint16_t get_message_number(unsigned char* message) {
    uint16_t message_info = nbo2hbo16(((uint16_t*)message)[3]);
    return message_info & 0x0FFF;
}

